/* Cygne
*
* Copyright notice for this file:
*  Copyright (C) 2002 Dox dox@space.pl
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "system.h"

#include <cstring>

namespace MDFN_IEN_WSWAN
{

	void GFX::InvalidByAddr(uint32 ws_offset)
	{
		if(wsVMode  && (ws_offset>=0x4000)&&(ws_offset<0x8000))
		{
			wsTCacheUpdate[(ws_offset-0x4000)>>5]=FALSE; /*invalidate tile*/
			return;
		}
		else if((ws_offset>=0x2000)&&(ws_offset<0x4000))
		{
			wsTCacheUpdate[(ws_offset-0x2000)>>4]=FALSE; /*invalidate tile*/
			return;
		}

		if(wsVMode  && (ws_offset>=0x8000)&&(ws_offset<0xc000))
		{
			wsTCacheUpdate2[(ws_offset-0x8000)>>5]=FALSE; /*invalidate tile*/
			return;
		}
		else if((ws_offset>=0x4000)&&(ws_offset<0x6000))
		{
			wsTCacheUpdate2[(ws_offset-0x4000)>>4]=FALSE; /*invalidate tile*/
			return;
		}
	}

	void GFX::SetVideo(int number,bool force)
	{
		if((number!=wsVMode)||(force))
		{ 
			wsVMode=number;
			std::memset(wsTCacheUpdate,0,512);
			std::memset(wsTCacheUpdate2,0,512);
		}
	}

	void GFX::MakeTiles()
	{
		int	x,y,b0,b1,b2,b3,b4,b5,b6,b7;
		for(x=0;x<256;x++)
			for(y=0;y<256;y++)
			{
				b0=(x&128)>>7;b1=(x&64)>>6;b2=(x&32)>>5;b3=(x&16)>>4;b4=(x&8)>>3;b5=(x&4)>>2;b6=(x&2)>>1;b7=(x&1);
				b0|=(y&128)>>6;b1|=(y&64)>>5;b2|=(y&32)>>4;b3|=(y&16)>>3;b4|=(y&8)>>2;b5|=(y&4)>>1;b6|=(y&2);b7|=(y&1)<<1;
				tiles[x][y][0][0]=b0;
				tiles[x][y][0][1]=b1;
				tiles[x][y][0][2]=b2;
				tiles[x][y][0][3]=b3;
				tiles[x][y][0][4]=b4;
				tiles[x][y][0][5]=b5;
				tiles[x][y][0][6]=b6;
				tiles[x][y][0][7]=b7;
				tiles[x][y][1][0]=b7;
				tiles[x][y][1][1]=b6;
				tiles[x][y][1][2]=b5;
				tiles[x][y][1][3]=b4;
				tiles[x][y][1][4]=b3;
				tiles[x][y][1][5]=b2;
				tiles[x][y][1][6]=b1;
				tiles[x][y][1][7]=b0;
			}
	}

	void GFX::GetTile(uint32 number,uint32 line,int flipv,int fliph,int bank)
	{
		uint32		t_adr,t_index,i;
		uint8		byte0,byte1,byte2,byte3;
		const uint8 *ram = sys->memory.wsRAM;

		if((!bank)||(!(wsVMode &0x07)))
		{
			if(!wsTCacheUpdate[number])
			{
				wsTCacheUpdate[number]=true;
				switch(wsVMode)
				{
				case 7:
					t_adr=0x4000+(number<<5);
					t_index=number<<6;
					for(i=0;i<8;i++)
					{
						byte0=ram[t_adr++];
						byte1=ram[t_adr++];
						byte2=ram[t_adr++];
						byte3=ram[t_adr++];
						wsTCache[t_index]=byte0>>4;
						wsTCacheFlipped[t_index++]=byte3&15;
						wsTCache[t_index]=byte0&15;
						wsTCacheFlipped[t_index++]=byte3>>4;
						wsTCache[t_index]=byte1>>4;
						wsTCacheFlipped[t_index++]=byte2&15;
						wsTCache[t_index]=byte1&15;
						wsTCacheFlipped[t_index++]=byte2>>4;
						wsTCache[t_index]=byte2>>4;
						wsTCacheFlipped[t_index++]=byte1&15;
						wsTCache[t_index]=byte2&15;
						wsTCacheFlipped[t_index++]=byte1>>4;
						wsTCache[t_index]=byte3>>4;
						wsTCacheFlipped[t_index++]=byte0&15;
						wsTCache[t_index]=byte3&15;
						wsTCacheFlipped[t_index++]=byte0>>4;
					}
					break;

				case 6:
					t_adr=0x4000+(number<<5);
					t_index=number<<6;
					for(i=0;i<8;i++)
					{
						byte0=ram[t_adr++];
						byte1=ram[t_adr++];
						byte2=ram[t_adr++];
						byte3=ram[t_adr++];
						wsTCache[t_index]=((byte0>>7)&1)|(((byte1>>7)&1)<<1)|(((byte2>>7)&1)<<2)|(((byte3>>7)&1)<<3);
						wsTCacheFlipped[t_index++]=((byte0)&1)|(((byte1)&1)<<1)|(((byte2)&1)<<2)|(((byte3)&1)<<3);
						wsTCache[t_index]=((byte0>>6)&1)|(((byte1>>6)&1)<<1)|(((byte2>>6)&1)<<2)|(((byte3>>6)&1)<<3);
						wsTCacheFlipped[t_index++]=((byte0>>1)&1)|(((byte1>>1)&1)<<1)|(((byte2>>1)&1)<<2)|(((byte3>>1)&1)<<3);
						wsTCache[t_index]=((byte0>>5)&1)|(((byte1>>5)&1)<<1)|(((byte2>>5)&1)<<2)|(((byte3>>5)&1)<<3);
						wsTCacheFlipped[t_index++]=((byte0>>2)&1)|(((byte1>>2)&1)<<1)|(((byte2>>2)&1)<<2)|(((byte3>>2)&1)<<3);
						wsTCache[t_index]=((byte0>>4)&1)|(((byte1>>4)&1)<<1)|(((byte2>>4)&1)<<2)|(((byte3>>4)&1)<<3);
						wsTCacheFlipped[t_index++]=((byte0>>3)&1)|(((byte1>>3)&1)<<1)|(((byte2>>3)&1)<<2)|(((byte3>>3)&1)<<3);
						wsTCache[t_index]=((byte0>>3)&1)|(((byte1>>3)&1)<<1)|(((byte2>>3)&1)<<2)|(((byte3>>3)&1)<<3);
						wsTCacheFlipped[t_index++]=((byte0>>4)&1)|(((byte1>>4)&1)<<1)|(((byte2>>4)&1)<<2)|(((byte3>>4)&1)<<3);
						wsTCache[t_index]=((byte0>>2)&1)|(((byte1>>2)&1)<<1)|(((byte2>>2)&1)<<2)|(((byte3>>2)&1)<<3);
						wsTCacheFlipped[t_index++]=((byte0>>5)&1)|(((byte1>>5)&1)<<1)|(((byte2>>5)&1)<<2)|(((byte3>>5)&1)<<3);
						wsTCache[t_index]=((byte0>>1)&1)|(((byte1>>1)&1)<<1)|(((byte2>>1)&1)<<2)|(((byte3>>1)&1)<<3);
						wsTCacheFlipped[t_index++]=((byte0>>6)&1)|(((byte1>>6)&1)<<1)|(((byte2>>6)&1)<<2)|(((byte3>>6)&1)<<3);
						wsTCache[t_index]=((byte0)&1)|(((byte1)&1)<<1)|(((byte2)&1)<<2)|(((byte3)&1)<<3);
						wsTCacheFlipped[t_index++]=((byte0>>7)&1)|(((byte1>>7)&1)<<1)|(((byte2>>7)&1)<<2)|(((byte3>>7)&1)<<3);
					}
					break;

				default:
					t_adr=0x2000+(number<<4);
					t_index=number<<6;
					for(i=0;i<8;i++)
					{
						byte0=ram[t_adr++];
						byte1=ram[t_adr++];
						wsTCache[t_index]=tiles[byte0][byte1][0][0];
						wsTCacheFlipped[t_index++]=tiles[byte0][byte1][1][0];
						wsTCache[t_index]=tiles[byte0][byte1][0][1];
						wsTCacheFlipped[t_index++]=tiles[byte0][byte1][1][1];
						wsTCache[t_index]=tiles[byte0][byte1][0][2];
						wsTCacheFlipped[t_index++]=tiles[byte0][byte1][1][2];
						wsTCache[t_index]=tiles[byte0][byte1][0][3];
						wsTCacheFlipped[t_index++]=tiles[byte0][byte1][1][3];
						wsTCache[t_index]=tiles[byte0][byte1][0][4];
						wsTCacheFlipped[t_index++]=tiles[byte0][byte1][1][4];
						wsTCache[t_index]=tiles[byte0][byte1][0][5];
						wsTCacheFlipped[t_index++]=tiles[byte0][byte1][1][5];
						wsTCache[t_index]=tiles[byte0][byte1][0][6];
						wsTCacheFlipped[t_index++]=tiles[byte0][byte1][1][6];
						wsTCache[t_index]=tiles[byte0][byte1][0][7];
						wsTCacheFlipped[t_index++]=tiles[byte0][byte1][1][7];
					}
				}
			}
			if(flipv)
				line=7-line;
			if(fliph)
				memcpy(&wsTileRow[0],&wsTCacheFlipped[(number<<6)|(line<<3)],8);
			else
				memcpy(&wsTileRow[0],&wsTCache[(number<<6)|(line<<3)],8);
		}
		else
		{


			if(!wsTCacheUpdate2[number])
			{
				wsTCacheUpdate2[number]=TRUE;
				switch(wsVMode)
				{
				case 7:
					t_adr=0x8000+(number<<5);
					t_index=number<<6;
					for(i=0;i<8;i++)
					{
						byte0=ram[t_adr++];
						byte1=ram[t_adr++];
						byte2=ram[t_adr++];
						byte3=ram[t_adr++];
						wsTCache2[t_index]=byte0>>4;
						wsTCacheFlipped2[t_index++]=byte3&15;
						wsTCache2[t_index]=byte0&15;
						wsTCacheFlipped2[t_index++]=byte3>>4;
						wsTCache2[t_index]=byte1>>4;
						wsTCacheFlipped2[t_index++]=byte2&15;
						wsTCache2[t_index]=byte1&15;
						wsTCacheFlipped2[t_index++]=byte2>>4;
						wsTCache2[t_index]=byte2>>4;
						wsTCacheFlipped2[t_index++]=byte1&15;
						wsTCache2[t_index]=byte2&15;
						wsTCacheFlipped2[t_index++]=byte1>>4;
						wsTCache2[t_index]=byte3>>4;
						wsTCacheFlipped2[t_index++]=byte0&15;
						wsTCache2[t_index]=byte3&15;
						wsTCacheFlipped2[t_index++]=byte0>>4;
					}
					break;
				case 6:
					t_adr=0x8000+(number<<5);
					t_index=number<<6;
					for(i=0;i<8;i++)
					{
						byte0=ram[t_adr++];
						byte1=ram[t_adr++];
						byte2=ram[t_adr++];
						byte3=ram[t_adr++];
						wsTCache2[t_index]=((byte0>>7)&1)|(((byte1>>7)&1)<<1)|(((byte2>>7)&1)<<2)|(((byte3>>7)&1)<<3);
						wsTCacheFlipped2[t_index++]=((byte0)&1)|(((byte1)&1)<<1)|(((byte2)&1)<<2)|(((byte3)&1)<<3);
						wsTCache2[t_index]=((byte0>>6)&1)|(((byte1>>6)&1)<<1)|(((byte2>>6)&1)<<2)|(((byte3>>6)&1)<<3);
						wsTCacheFlipped2[t_index++]=((byte0>>1)&1)|(((byte1>>1)&1)<<1)|(((byte2>>1)&1)<<2)|(((byte3>>1)&1)<<3);
						wsTCache2[t_index]=((byte0>>5)&1)|(((byte1>>5)&1)<<1)|(((byte2>>5)&1)<<2)|(((byte3>>5)&1)<<3);
						wsTCacheFlipped2[t_index++]=((byte0>>2)&1)|(((byte1>>2)&1)<<1)|(((byte2>>2)&1)<<2)|(((byte3>>2)&1)<<3);
						wsTCache2[t_index]=((byte0>>4)&1)|(((byte1>>4)&1)<<1)|(((byte2>>4)&1)<<2)|(((byte3>>4)&1)<<3);
						wsTCacheFlipped2[t_index++]=((byte0>>3)&1)|(((byte1>>3)&1)<<1)|(((byte2>>3)&1)<<2)|(((byte3>>3)&1)<<3);
						wsTCache2[t_index]=((byte0>>3)&1)|(((byte1>>3)&1)<<1)|(((byte2>>3)&1)<<2)|(((byte3>>3)&1)<<3);
						wsTCacheFlipped2[t_index++]=((byte0>>4)&1)|(((byte1>>4)&1)<<1)|(((byte2>>4)&1)<<2)|(((byte3>>4)&1)<<3);
						wsTCache2[t_index]=((byte0>>2)&1)|(((byte1>>2)&1)<<1)|(((byte2>>2)&1)<<2)|(((byte3>>2)&1)<<3);
						wsTCacheFlipped2[t_index++]=((byte0>>5)&1)|(((byte1>>5)&1)<<1)|(((byte2>>5)&1)<<2)|(((byte3>>5)&1)<<3);
						wsTCache2[t_index]=((byte0>>1)&1)|(((byte1>>1)&1)<<1)|(((byte2>>1)&1)<<2)|(((byte3>>1)&1)<<3);
						wsTCacheFlipped2[t_index++]=((byte0>>6)&1)|(((byte1>>6)&1)<<1)|(((byte2>>6)&1)<<2)|(((byte3>>6)&1)<<3);
						wsTCache2[t_index]=((byte0)&1)|(((byte1)&1)<<1)|(((byte2)&1)<<2)|(((byte3)&1)<<3);
						wsTCacheFlipped2[t_index++]=((byte0>>7)&1)|(((byte1>>7)&1)<<1)|(((byte2>>7)&1)<<2)|(((byte3>>7)&1)<<3);
					}
					break;
				default:
					t_adr=0x4000+(number<<4);
					t_index=number<<6;
					for(i=0;i<8;i++)
					{
						byte0=ram[t_adr++];
						byte1=ram[t_adr++];
						wsTCache2[t_index]=tiles[byte0][byte1][0][0];
						wsTCacheFlipped2[t_index++]=tiles[byte0][byte1][1][0];
						wsTCache2[t_index]=tiles[byte0][byte1][0][1];
						wsTCacheFlipped2[t_index++]=tiles[byte0][byte1][1][1];
						wsTCache2[t_index]=tiles[byte0][byte1][0][2];
						wsTCacheFlipped2[t_index++]=tiles[byte0][byte1][1][2];
						wsTCache2[t_index]=tiles[byte0][byte1][0][3];
						wsTCacheFlipped2[t_index++]=tiles[byte0][byte1][1][3];
						wsTCache2[t_index]=tiles[byte0][byte1][0][4];
						wsTCacheFlipped2[t_index++]=tiles[byte0][byte1][1][4];
						wsTCache2[t_index]=tiles[byte0][byte1][0][5];
						wsTCacheFlipped2[t_index++]=tiles[byte0][byte1][1][5];
						wsTCache2[t_index]=tiles[byte0][byte1][0][6];
						wsTCacheFlipped2[t_index++]=tiles[byte0][byte1][1][6];
						wsTCache2[t_index]=tiles[byte0][byte1][0][7];
						wsTCacheFlipped2[t_index++]=tiles[byte0][byte1][1][7];
					}
				}	
			}
			if(flipv)
				line=7-line;
			if(fliph)
				memcpy(&wsTileRow[0],&wsTCacheFlipped2[(number<<6)|(line<<3)],8);
			else
				memcpy(&wsTileRow[0],&wsTCache2[(number<<6)|(line<<3)],8);
		}
	}

}
